﻿/*****************************************************
 * File:            TestCaseExecutor.cs
 * Description:     Test Case Executor (used with offline test case generator)
 * By:              Ali Khalili (khalili DOT ir AT gmail DOT com)
 * Project:         Automata Learning
 * Requirements:    
 * Change log:
 *          -1 May 2013: Initial Version
 * To Do:
 *          -
 * License:
 *****************************************************/

using System;
using System.Collections.Generic;
using SMLib.Automata.MM;
using SMLib.Automata.Base;

namespace MBT.Conformance.TestExecution
{
    /// <summary>
    /// Test Case Executor for Mealy Machines
    /// <remarks>A test executor will be used in offline test case execution when an offline
    /// test case generator is used to generate a set of test cases</remarks>
    /// </summary>
    public class TestCaseExecutor
    {
        MealyMachine machine;
        bool determ;
        IBlackBox_MM SUT;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="automaton">the underlaying automaton</param>
        /// <param name="deterministic">it is deterministic or not</param>
        public TestCaseExecutor(IBlackBox_MM SUT, MealyMachine automaton, bool deterministic)
        {
            this.SUT = SUT;
            this.machine = automaton;
            this.determ = deterministic;
        }


        /// <summary>
        /// Try a test case by executing it on SUT
        /// </summary>
        /// <param name="input">the input test sequence</param>
        /// <param name="output">the obtained result from SUT</param>
        /// <returns>true if the output maches, false in other case</returns>
        public bool TryTestCase(List<ISymbol> input, out List<ISymbol> output)
        {
            //* reset the system
            //LearningLog.LogStartSULReset();
            SUT.Reset();
            //LearningLog.LogFinishSULReset();

            output = new List<ISymbol>();
            MealyMachine.Mealy_State cur = (MealyMachine.Mealy_State)machine[0];

            //LearningLog.LogStartQueryOnSUL();
            for (int i = 0; i < input.Count; i++)
            {
                //* Step the system
                ISymbol sutOt = SUT.Step(input[i]);
                output.Add(sutOt);
                
                //* [We may remove the "determ"?]
                if (determ)
                {
                    List<ISymbol> allowedOp = cur.ListOfAllOutputs(input[i]);
                    if (allowedOp.Contains(sutOt))
                    {
                        cur = cur.NextNode(input[i]);
                    }
                    else
                    {
                        //LearningLog.LogFinishQueryOnSUL();
                        return false;
                    }
                }
                else
                {
                    List<ISymbol> allowedOp = cur.ListOfAllOutputs(input[i]);
                    if (allowedOp.Contains(sutOt))
                    {
                        cur = cur.NextNode(input[i], sutOt);
                    }
                    else
                    {
                        //LearningLog.LogFinishQueryOnSUL(); 
                        return false;
                    }
                }
            }

            //LearningLog.LogFinishQueryOnSUL();
            return true;
        }
    }
}
